/*
 * Copyright (c) Ulrich Hilger, http://dev.uhilger.de, all rights reserved.
 *
 * Published under the terms and conditions of the Apache License 2.0,
 * see http://www.apache.org/licenses/LICENSE-2.0
 */

package de.uhilger.servicehub.server;

import de.uhilger.servicehub.model.JDBCUserStore;
import de.uhilger.servicehub.model.ServletContainer;
import de.uhilger.servicehub.model.UserStore;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.handler.HandlerList;
import org.eclipse.jetty.webapp.WebAppContext;

/**
 * <p>An embedded Jetty server</p>
 *
 * @author Ulrich Hilger, <a href="http://dev.uhilger.de" target="_blank">http://dev.uhilger.de</a>
 * @author Published under the terms and conditions of
 * the <a href="http://www.apache.org/licenses/LICENSE-2.0" target="_blank">Apache License 2.0</a>
 */
public class EmbeddedJetty implements ServletContainer {

  public static final String SERVLET_CONTAINER_NAME = "Jetty";

  private String base;
  private String home;
  private org.eclipse.jetty.server.Server server;
  private UserStore store;
  private String userStorageName;
  private int port;
  private StartJettyThread serverThread;
  private String user;
  private String password;

  public EmbeddedJetty() {
    super();
  }

  public void setServer(org.eclipse.jetty.server.Server server) {
    this.server = server;
  }

  public org.eclipse.jetty.server.Server getServer() {
    return server;
  }

  public int getPort() {
    return port;
  }

  public boolean contextPathExists(String contextPath) {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void deployWAR(String contextPath, URL warFile) throws Exception {
    /*
    FileSystem fs = new LocalFileSystem();
    try {
      FileRef[] filesToCopy = new FileRef[1];
      filesToCopy[0] = new FileRef(warFile);
      fs.copy(filesToCopy, new FileRef(getBase() +
        File.separator + ServletContainer.DEFAULT_WEBAPPS_PATH + File.separator + contextPath, true));
      /*fs.extract(new FileRef(warFile), new FileRef(getBase() +
        File.separator + ServletContainer.DEFAULT_WEBAPPS_PATH + File.separator + contextPath, true));*/
    /*} catch (Throwable ex) {
      ServiceHub.logStackTrace(ex, getClass());
    }
    */
  }

  public String[] getApps() {
    Handler[] appContexts = server.getHandlers();
    List list = new ArrayList();
    //Container[] appContexts = tomcat.getApps();
    for (int i = 0; i < appContexts.length; i++) {
      if (appContexts[i] != null && appContexts[i] instanceof WebAppContext) {
        WebAppContext context = (WebAppContext) appContexts[i];
        //ServiceHub.log("getApps adds context path " + context.getDisplayName() + " to list", getClass(), Level.FINEST);
        //ServiceHub.log("getApps context doc base " + context.getDocBase(), getClass(), Level.FINEST);
        String contextPath = context.getContextPath();
        if (contextPath != null && contextPath.length() > 1) {
          list.add(contextPath + ": " + context.getDisplayName());
        } else {
          list.add(URL_SEPARATOR + ": " + context.getDisplayName());
        }
      } else if(appContexts[i] instanceof HandlerList) {
        HandlerList hList = (HandlerList) appContexts[i];
        Handler[] handlers = hList.getHandlers();
        for(int k = 0; k < handlers.length; k++) {
          list.add(((WebAppContext) handlers[k]).getContextPath() + ": " + ((WebAppContext) handlers[k]).getDisplayName());
        }
      }
    }
    return (String[]) list.toArray(new String[0]);
  }

  public String getBase() {
    return base;
  }

  public String getHome() {
    return home;
  }

  public String getInfo() {
    return SERVLET_CONTAINER_NAME + " " + org.eclipse.jetty.server.Server.getVersion();
  }

  public void registerWAR(String contextPath, String absolutePath) throws Exception {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void setBase(String basePath) {
    this.base = basePath;
  }

  public void setHome(String homePath) {
    this.home = homePath;
  }

  public void start(int port) throws Exception {
    //System.setProperty("jetty.home",getBase());
    //File file = new File(getBase() + "/conf/jetty.xml");
    //FileReader fr = new FileReader(file)
        //Resource jetty_xml = Resource.newSystemResource(getBase() + "/conf/jetty.xml");
        //XmlConfiguration configuration = new XmlConfiguration(getBase() + "/conf/jetty.xml");
        //server = (org.eclipse.jetty.server.Server)configuration.configure();

    this.port = port;
    serverThread = new StartJettyThread(this);
    serverThread.setBase(getBase());
    serverThread.start();
    /*
    server = new org.eclipse.jetty.server.Server(port);

    JDBCLoginService jdbcLoginService = new JDBCLoginService();
    jdbcLoginService.setConfig(getBase() + "/conf/jdbcRealm.properties");
    ConstraintSecurityHandler secHandler = new ConstraintSecurityHandler();
    secHandler.setLoginService(jdbcLoginService);

    WebAppContext webapp = new WebAppContext();
    webapp.setSecurityHandler(secHandler);
    webapp.setContextPath("/AudioHub");
    webapp.setWar(getBase()+"/webapps/AudioHub");
    server.setHandler(webapp);

    server.start();
    */
    /*while(!server.isRunning()) {
      // wait
    }*/
    //server.join();
  }

  public void stop() throws Exception {
    serverThread.stopThread();
  }

  public void unregisterWAR(String contextPath) throws Exception {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void setUserStore(UserStore userStore) {
    this.store = userStore;
    if(userStore instanceof JDBCUserStore) {
      JDBCUserStore jdbcStore = (JDBCUserStore) userStore;
  		try { Class.forName(jdbcStore.getJDBCDriverClassName()).newInstance(); }
    	catch (Exception e) { e.printStackTrace(); }
    }
  }

  public void setUserStorageName(String storageName) {
    this.userStorageName = storageName;
  }

  public void setDbUser(String dbUser) {
    this.user = dbUser;
  }

  public void setDbPassword(String dbPass) {
    this.password = dbPass;
  }


}
